package com.aij.ims.server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.aij.ims.channel.WebSocketChannel;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.net.InetSocketAddress;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class WebSocketServer {

	private Logger logger = LoggerFactory.getLogger(WebSocketServer.class);
	 
	@Value("${netty.websocket.port}")
	private Integer port;
    		
	/**
	* boss 线程组用于处理连接工作
	*/
	private EventLoopGroup boss = new NioEventLoopGroup();
	/**
	* work 线程组用于数据处理
	*/
	private EventLoopGroup work = new NioEventLoopGroup();
	
	private ServerBootstrap serverBootstrap = new ServerBootstrap();
	
	@PostConstruct
	public void start() {
	     serverBootstrap = new ServerBootstrap();
	     // 初始化服务器启动对象
	     serverBootstrap
	         // 指定使用上面创建的两个线程池
	         .group(boss, work)
	         
	         // 指定Netty通道类型
	         .channel(NioServerSocketChannel.class)
	  
	         //使用指定的端口设置套接字地址
	         .localAddress(new InetSocketAddress(port))
	         
	          //服务端可连接队列数,对应TCP/IP协议listen函数中backlog参数
	         .option(ChannelOption.SO_BACKLOG, 1024)
	  
	         //设置TCP长连接,一般如果两个小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
	         .childOption(ChannelOption.SO_KEEPALIVE, true)
	  
	         //将小的数据包包装成更大的帧进行传送，提高网络的负载,即TCP延迟传输
	         .childOption(ChannelOption.TCP_NODELAY, true)
	         
	         // 指定通道初始化器用来加载当Channel收到事件消息后
	         .childHandler(new WebSocketChannel());
	     ChannelFuture future;
		try {
			future = serverBootstrap.bind().sync();
		     if (future.isSuccess()) {
		    	 logger.info("启动 WebSocket Server 0.0.0.0:" + port);
		     }
		} catch (InterruptedException e) {
			logger.error(e.getMessage() + e.getStackTrace().toString());
		}
	}
	
	@PreDestroy
	public void destory() throws InterruptedException {
		boss.shutdownGracefully().sync();
		work.shutdownGracefully().sync();
		logger.info("关闭 WebSocket Server");
	}
}

